#!/usr/bin/python3
# -*- coding: UTF-8 -*-


import os
import sys
import sqlite3
from pynput import keyboard
from PyQt5.QtWidgets import QApplication, QWidget, QPushButton, QLineEdit, QLabel, QLayout, QGridLayout, QTableWidgetItem, QHeaderView, QScrollBar, QVBoxLayout, QAbstractItemView, QMenu, QMenuBar, QAction, QFileIconProvider, QSystemTrayIcon
from PyQt5.QtCore import QThread, pyqtSignal, Qt, QFileInfo, QEvent, QObject, QCoreApplication, QMimeData, QUrl
from PyQt5.QtGui import QIcon, QPixmap, QCloseEvent
# from qs import Qs, SqlRunner
from Ui_mianframe import Ui_Form
import win32api
import win32com.client

if win32com.client.gencache.is_readonly == True:

    # allow gencache to create the cached wrapper objects
    win32com.client.gencache.is_readonly = False

    # under p2exe the call in gencache to __init__() does not happen
    # so we use Rebuild() to force the creation of the gen_py folder
    win32com.client.gencache.Rebuild()


conn = sqlite3.connect('D:\MyConfiguration\gwf08576\AppData\Local\Programs\Python\Python37\Lib\site-packages\win32\index.db', check_same_thread=False)
c = conn.cursor()

class MainFrame(QWidget, Ui_Form):

    def __init__(self):
        super(MainFrame, self).__init__()
        self.setupUi(self)
        self.clipboard = QApplication.clipboard()

        self.setWindowIcon(QIcon('trayicon.png'))
        self.trayicon = QSystemTrayIcon(QIcon('trayicon.png'), self)
        self.trayicon.activated.connect(self.trayiconActivated)

        self.traymenu = QMenu()
        self.traymenu.addAction(QAction('Open', self))
        self.traymenu.addAction(QAction('Exit', self))
        self.traymenu.triggered.connect(self.traymenuselected)
        self.trayicon.setContextMenu(self.traymenu)
        self.trayicon.show()

        self.thread = Worker()
        self.thread.finishedSig.connect(self.fillResult)

        self.keyboardListener = KeyboardListener()
        self.keyboardListener.showSignal.connect(self.show)
        self.keyboardListener.start()

        self.dataCount = 0
        self.pageIndex = 0
        self.pageSize = 100

        heigth = self.tableWidget.rowHeight(0)
        scroll = QScrollBar(self.tableWidget)
        scroll.setMaximum(heigth * self.pageSize)
        scroll.valueChanged.connect(self.page)
        scroll.sliderMoved.connect(self.page)
        self.tableWidget.setVerticalScrollBar(scroll)

        self.setWindowFlags(Qt.CustomizeWindowHint |
                            Qt.WindowTitleHint | Qt.WindowCloseButtonHint)

    def closeEvent(self, event):
        print(event)
        event.ignore()
        self.hide()

    def trayiconActivated(self, reason):
        if reason != QSystemTrayIcon.Context:
            self.lineEdit.setFocus()
            self.show()

    def focusOutEvent(self, event):
        self.hide()

    def onSearch(self, keywords):
        self.pageIndex = 0
        self.dataCount = 0
        self.tableWidget.setRowCount(0)
        self.tableWidget.clearContents()
        if keywords != '':
            try:
                self.thread.setKeywords(
                    self.lineEdit.text(), self.pageSize, self.pageIndex)
                self.thread.start()
            except BaseException as e:
                print(e)

    def fillResult(self, result):
        self.dataCount = len(result)

        if self.dataCount > 0:
            rangeData = self.pageSize
            if self.dataCount < self.pageSize:
                rangeData = self.dataCount

            rowCount = self.pageIndex * self.pageSize + rangeData
            self.tableWidget.setRowCount(rowCount)
            for index in range(rangeData):
                name = QTableWidgetItem(result[index][0])
                path = QTableWidgetItem(result[index][1])

                fullpath = os.path.join(result[index][1], result[index][0])
                fileInfo = QFileInfo(fullpath)
                fileProvider = QFileIconProvider()
                icon = fileProvider.icon(fileInfo)
                name.setIcon(icon)

                rowIndex = self.pageIndex * self.pageSize + index
                self.tableWidget.setItem(rowIndex, 0, name)
                self.tableWidget.setItem(rowIndex, 1, path)

    def page(self, value):
        if value == self.tableWidget.verticalScrollBar().maximum() and self.dataCount == self.pageSize:
            self.pageIndex += 1
            self.thread.setKeywords(
                self.lineEdit.text(), self.pageSize, self.pageIndex)
            self.thread.start()

    def showMenu(self, pos):
        items = self.tableWidget.selectedItems()
        if len(items) > 0:
            menu = QMenu()
            open_m = menu.addAction('Open')
            opend_m = menu.addAction('Open directory')
            copy_m = menu.addAction('copy')
            copyd_m = menu.addAction('copy directory')
            action = menu.exec_(self.tableWidget.mapToGlobal(pos))

            fullpath = '{}\\{}'.format(items[1].text(), items[0].text())
            if action == open_m:
                if os.path.isdir(fullpath) == True:
                    # os.system('explorer.exe \"%s\"' % fullpath)
                    win32api.ShellExecute(0, 'explore', fullpath, '', '', 1)
                else:
                    # os.system('"%s"' % fullpath)
                    win32api.ShellExecute(0, 'open', fullpath, '', '', 1)
            elif action == opend_m:
                # os.system('explorer.exe \"%s\"' % items[1].text())
                    win32api.ShellExecute(0, 'explore', items[1].text(), '', '', 1)
            elif action == copy_m:
                data = QMimeData()
                url = QUrl.fromLocalFile(fullpath)
                data.setUrls([url])
                self.clipboard.setMimeData(data)
            elif action == copyd_m:
                self.clipboard.setText(fullpath)

    def traymenuselected(self, action):
        if action.text().lower() == 'open':
            self.show()
            self.lineEdit.setFocus()
        elif action.text().lower() == 'exit':
            QCoreApplication.exit()
        self.traymenu.hideTearOffMenu()


class Worker(QThread):
    '''异步从sqlite3查询数据.
    通过QThread线程查询数据以防止界面卡死.
    '''

    finishedSig = pyqtSignal(list)

    def __init__(self, parent=None):
        super(Worker, self).__init__(parent)
        self.working = True

    def setKeywords(self, keywords, pageSize, pageIndex):
        '''设置分页查询数据条件.

        Args:
            keywords: 关键字.
            pageSize: 每页数据量.
            pageIndex: 当前页码,从0开始.

        Returns:
            void
        '''
        self.keywords = keywords
        self.pageSize = pageSize
        self.pageIndex = pageIndex

    def __del__(self):
        self.working = False
        self.wait()

    def run(self):
        c.execute("SELECT NAME,PATH FROM F WHERE NAME LIKE '%" +
                  self.keywords+"%' ORDER BY LENGTH(NAME) ASC, TYPE DESC LIMIT "+str(self.pageIndex*self.pageSize)+","+str(self.pageSize)+"")
        conn.commit()
        result = c.fetchall()
        self.finishedSig.emit(result)


class KeyboardListener(QThread):

    showSignal = pyqtSignal()
    hasrelease = False
    hasalt = False

    def __init__(self, parent=None):
        super(KeyboardListener, self).__init__(parent)

    def run(self):
        with keyboard.Listener(
            on_press=self.on_press,
            on_release=self.on_release
        ) as listener:
            listener.join()

    def on_press(self, key):
        key_char = key.char if isinstance(key, keyboard.KeyCode) else str(key)
        if key == keyboard.Key.alt_l or key == keyboard.Key.alt_r:
            self.hasalt = True
        elif self.hasalt == True and key_char == 'w':
            print('show')
            self.showSignal.emit()

    def on_release(self, key):
        if key == keyboard.Key.alt_l or key == keyboard.Key.alt_r:
            self.hasalt = False
        self.hasrelease = True


if __name__ == '__main__':

    app = QApplication(sys.argv)
    m = MainFrame()
    m.lineEdit.textChanged.connect(m.onSearch)

    m.tableWidget.setHorizontalHeaderLabels(['名称', '路径'])
    m.tableWidget.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
    m.tableWidget.setColumnCount(2)
    m.tableWidget.setSelectionBehavior(QAbstractItemView.SelectRows)

    m.tableWidget.setContextMenuPolicy(Qt.CustomContextMenu)
    m.tableWidget.customContextMenuRequested.connect(m.showMenu)

    m.setWindowTitle('Quck Search')
    # m.setDisabled(True)
    m.show()
    app.exec_()
    sys.exit()
